import socket  # 导入 socket 模块
from threading import Thread
import time
import json

import pika
from queue import Queue
# https://blog.csdn.net/linxinfa/article/details/104001443

ADDRESS = ('0.0.0.0', 8080)  # 绑定地址
 
g_socket_server = None  # 负责监听的socket
 
g_conn_pool = {}  # 连接池

#基本FIFO队列  先进先出 FIFO即First in First Out,先进先出
FIFO = Queue(maxsize=0) #maxsize设置队列中，数据上限，小于或等于0则不限制，容器中大于这个数则阻塞，直到队列中的数据被消掉
FIFO_sand = Queue(maxsize=0) #maxsize设置队列中，数据上限，小于或等于0则不限制，容器中大于这个数则阻塞，直到队列中的数据被消掉

channelx = None

#消息处理函数，执行完成才说明接收完成，此时才可以接收下一条，串行
def dongcallbackfun(v1,v2,v3,bodyx):
    print("django通过queen发送了数据给tcp:",bodyx)
    FIFO.put(bodyx)
    print(FIFO.qsize(), FIFO.queue)

def queue_init_sand():
    #建立连接
    userx=pika.PlainCredentials("ruroot","rproot")
    conn=pika.BlockingConnection(pika.ConnectionParameters("0.0.0.0",5672,'/',credentials=userx))
    #开辟管道
    channelx=conn.channel()
    #声明队列，参数为队列名
    channelx.queue_declare(queue="client")
    return channelx

def queue_init_rev():
    #建立连接
    userx=pika.PlainCredentials("ruroot","rproot")
    conn=pika.BlockingConnection(pika.ConnectionParameters("0.0.0.0",5672,'/',credentials=userx))
    #开辟管道
    channelx=conn.channel()
    #声明队列，参数为队列名
    channelx.queue_declare(queue="queue_rev")
    return channelx

def queue_rev(obj,data):
    #接收准备
    obj.basic_consume(queue="queue_rev", #队列名
                        on_message_callback=dongcallbackfun, #收到消息的回调函数 
                        auto_ack=True #是否发送消息确认
                        )
    print("queue开始接收数据")

    #开始接收消息
    obj.start_consuming()

def queue_sand(obj, datastr = "no data"):
    #发送数据，发送一条，如果要发送多条则复制此段
    obj.basic_publish(exchange="",
                        routing_key="queueu_sand",# 队列名
                        body="hello world" # 发送的数据
                        )
    print("rabit 发送数据完成 successful！", datastr)    


def init():
    """
    初始化服务端
    """
    global g_socket_server
    g_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
    g_socket_server.bind(ADDRESS)
    g_socket_server.listen(5)  # 最大等待数（有很多人理解为最大连接数，其实是错误的）
    print("初始化服务端")

def accept_client():
    obj_queue_rev = queue_init_rev()
    thread_queue = Thread(target=queue_rev, args=(obj_queue_rev, 0)) # 设备发送数据给django
    # 设置成守护线程
    thread_queue.setDaemon(True)
    thread_queue.start()
    """
    接收新连接
    """
    print("新创建服务器while(1)")
    while True:
        client, info = g_socket_server.accept()  # 阻塞，等待客户端连接
        print("新创建了一个客户端")
        thread2 = Thread(target=message_handle_rev, args=(None, client, info)) # 设备发送数据给django
        # 设置成守护线程
        thread2.setDaemon(True)
        thread2.start()

        # 给每个客户端创建一个独立的线程进行管理
        thread = Thread(target=message_handle_sand, args=(client, info)) # django发送数据给设备 
        # 设置成守护线程 
        thread.setDaemon(True)
        thread.start()
 
def message_handle_sand(client, info):
    """
    消息处理
    """
    client.sendall("connect server successfully!".encode(encoding='utf8'))
    print("新的客户端连接", client, FIFO.queue)
    while True:
        lists = FIFO.get(block=True, timeout=None) # 阻塞方式接收获取数据
        print("tcp设备的单独服务器接收到了从Dango传来的fifo", FIFO.queue)
        # do something
        print(lists)
        client.sendall("I have get message!".encode(encoding='utf8'))

def remove_client(client_type):
    client = g_conn_pool[client_type]
    if None != client:
        client.close()
        g_conn_pool.pop(client_type)
        print("client offline: " + client_type)

def message_handle_rev(obj, client, info):
    obj_queue_sand = queue_init_sand()
    """
    消息处理
    """
    print("新的客户端连接", client, FIFO.queue)
    while True:
        bytes = client.recv(1024)
        msg = bytes.decode(encoding='utf8')
        if(len(bytes)):
            # 
            print(info,"收到了数据：",msg, "发送数据到Django中")
            queue_sand(obj_queue_sand, datastr = "Django zhong")
        else:
            print("tcp断开了")
            remove_client(client)
            break
        
        


if __name__ == '__main__':
    init()
    print("创建 socket 线程")
    # 新开一个线程，用于接收新连接
    thread = Thread(target=accept_client)
    thread.setDaemon(True) # 设置守护线程
    thread.start()
    # 主线程逻辑
    while True:
        time.sleep(0.1)

